package dk.pun.aot.shared.user;

import java.io.Serializable;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import dk.pun.aot.shared.character.CharacterId;

@SuppressWarnings("serial")
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class UserData implements Serializable {

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Long key;

	@Persistent
	private String userId;
	@Persistent
	private String nickname;
	@Persistent
	private String email;
	@Persistent
	private Long selectedCharacterIdKey;
	@Persistent
	private String[] characterIdSetEncoded;
	
	@SuppressWarnings("unused")
	private UserData() {}

	public UserData(String userId) {
		this.userId = userId;
		this.nickname = userId;
	}
	
	public Long getKey() {
		return key;
	}

	public String getUserId() {
		return userId;
	}
	
	public String getNickname() {
		return nickname;
	}

	public void setNickname(String nickname) {
		this.nickname = nickname;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public CharacterId getSelectedCharacterId() {
		CharacterId selectedCharacterId = null;
		if (this.selectedCharacterIdKey != null && this.characterIdSetEncoded != null) {
			for (CharacterId characterId : this.getCharacterIdSet()) {
				if (characterId.getKey().equals(this.selectedCharacterIdKey)) {
					selectedCharacterId = characterId;
					break;
				}
			}
		}
		return selectedCharacterId;
	}

	public void setSelectedCharacterId(CharacterId selectedCharacterId) {
		if (selectedCharacterId != null) {
			this.selectedCharacterIdKey = selectedCharacterId.getKey();
		} else {
			this.selectedCharacterIdKey = null;
		}
	}

	public Iterator<CharacterId> getCharacterIdIterator() {
		return this.getCharacterIdSet().iterator();
	}

	public boolean addCharacterId(CharacterId characterId) {
		boolean result = false;
		if (characterId != null) {
			this.selectedCharacterIdKey = characterId.getKey();
			SortedSet<CharacterId> set = this.getCharacterIdSet();
			result = set.add(characterId);
			this.setCharacterIdSet(set);
		}
		return result;
	}

	public boolean updateCharacterId(CharacterId characterId) {
		boolean result = false;
		if (characterId != null) {
			SortedSet<CharacterId> set = this.getCharacterIdSet();
			for (CharacterId cid : set) {
				if (cid.getKey().equals(characterId.getKey())) {
					cid.setName(characterId.getName());
					result = true;
					break;
				}
			}
			result = set.add(characterId);
			this.setCharacterIdSet(set);
		}
		return result;
	}
	
	public boolean removeCharacterId(Object characterId) {
		boolean result = false;
		if (characterId != null && characterId instanceof CharacterId) {
			if (this.characterIdSetEncoded != null) {
				SortedSet<CharacterId> set = this.getCharacterIdSet();
				result = set.remove(characterId);
				this.setCharacterIdSet(set);
				if (result && this.selectedCharacterIdKey != null
						&& this.selectedCharacterIdKey.equals(((CharacterId)characterId).getKey())) {
					this.selectedCharacterIdKey = null;
				}
			}
		}
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		UserData other = (UserData) obj;
		if (key == null) {
			if (other.key != null)
				return false;
		} else if (!key.equals(other.key))
			return false;
		return true;
	}
	
	@Override
	public String toString() {
		return "UserData [userId=" + userId + ", nickname=" + nickname
				+ ", email=" + email + ", selectedCharacterIdKey="
				+ selectedCharacterIdKey + ", characterIdSet=" + this.getCharacterIdSet()
				+ "]";
	}

	private SortedSet<CharacterId> getCharacterIdSet() {
		SortedSet<CharacterId> set = new TreeSet<CharacterId>();
		if (this.characterIdSetEncoded != null) {
			for (int i=0; i<this.characterIdSetEncoded.length; i++) {
				Long key = Long.valueOf(this.characterIdSetEncoded[i++]);
				String name = this.characterIdSetEncoded[i];
				set.add(new CharacterId(key, name));
			}
		}
		return set;
	}
	
	private void setCharacterIdSet(SortedSet<CharacterId> characterIdSet) {
		if (characterIdSet != null) {
			String[] array = new String[characterIdSet.size()*2];
			int i = 0;
			for (CharacterId characterId : characterIdSet) {
				array[i++] = characterId.getKey().toString();
				array[i++] = characterId.getName();
			}
			this.characterIdSetEncoded = array;
		} else {
			this.characterIdSetEncoded = null;
		}
	}
	
}
